#include "asm/includes.h"
//#include "asm/ldo.h"
//#include "asm/cache.h"
#include "asm/wdt.h"
#include "asm/debug.h"
#include "asm/efuse.h"
#include "asm/power/p33.h"
#include "asm/efuse.h"
#include "system/task.h"
#include "timer.h"
#include "syscfg_id.h"
#include "app_config.h"
#include "gpio.h"

//#include "power_manage.h"
//
#define LOG_TAG_CONST       SETUP
#define LOG_TAG             "[SETUP]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"

//extern void dv15_dac_early_init(u8 ldo_sel, u8 pwr_sel, u32 dly_msecs);
//
extern void sys_timer_init(void);

extern void tick_timer_init(void);

extern u32 reset_source_dump(void);

extern u8 power_reset_source_dump(void);

extern void exception_irq_handler(void);
int __crc16_mutex_init();

extern int __crc16_mutex_init();

#define DEBUG_SINGAL_IDLE(x)        //if (x) IO_DEBUG_1(A, 7) else IO_DEBUG_0(A, 7)
#define DEBUG_SINGAL_1S(x)          //if (x) IO_DEBUG_1(A, 6) else IO_DEBUG_0(A, 6)

#if (defined CONFIG_DEBUG_ENABLE) || (defined CONFIG_DEBUG_LITE_ENABLE)
void debug_uart_init(const struct uart_platform_data *data);
#endif

#if 0
___interrupt
void exception_irq_handler(void)
{
    ___trig;

    exception_analyze();

    log_flush();
    while (1);
}
#endif



/*
 * 此函数在cpu0上电后首先被调用,负责初始化cpu内部模块
 *
 * 此函数返回后，操作系统才开始初始化并运行
 *
 */

#if 0
static void early_putchar(char a)
{
    if (a == '\n') {
        UT2_BUF = '\r';
        __asm_csync();
        while ((UT2_CON & BIT(15)) == 0);
    }
    UT2_BUF = a;
    __asm_csync();
    while ((UT2_CON & BIT(15)) == 0);
}

void early_puts(char *s)
{
    do {
        early_putchar(*s);
    } while (*(++s));
}
#endif

void cpu_assert_debug()
{
#ifdef CONFIG_DEBUG_ENABLE
    log_flush();
    local_irq_disable();
    while (1);
#else
    P3_PCNT_SET0 = 0xac;
    cpu_reset();
#endif
}

void timer(void *p)
{
    /* DEBUG_SINGAL_1S(1); */
    sys_timer_dump_time();
    /* DEBUG_SINGAL_1S(0);*/
}

void app_bank_init()
{
#ifdef CONFIG_CODE_BANK_ENABLE
    extern void bank_syscall_entry();
    request_irq(IRQ_SYSCALL_IDX, 3, bank_syscall_entry, 0);
    extern void load_common_code();
    load_common_code();
#endif
}
extern u8 SYS_24G_SN_BYTE[4];
u8 LSCOM[6];
static void (*uart_db_irq_handler_callback)(u8 *packet, u32 size);
extern void uart_dev_set_irq_handler_hook(void *uart_irq_hook);
static void uart_db_irq_handler_hook(u8 *rbuf, u32 len)
{
    u16 LSX;
    u8 i;
    if(len)
    {
      if(len==4)//控制回读使用的
      {
         if((rbuf[0]=='Y')&(rbuf[1]=='R'))
         {
             if((rbuf[2]==0xC2)&(rbuf[3]==0x6D))//回读遥控器密码值使用的
             {
               //printf("YR%#X%#X%#X",SYS_24G_SN_BYTE[0],SYS_24G_SN_BYTE[1],SYS_24G_SN_BYTE[2]);
               LSCOM[0]='Y';
               LSCOM[1]='R';
               LSCOM[2]=SYS_24G_SN_BYTE[0];//SN1
               LSCOM[3]=SYS_24G_SN_BYTE[1];//SN2
               LSCOM[4]=SYS_24G_SN_BYTE[2];//SN3
               //put_buf(LSCOM, 5);//发送返回串口值
               for(i=0;i<5;i++)
               {
                 //put_u8hex(LSCOM[i]);//测试一下是否是单个发送
                    if (JL_UART0->CON0 & BIT(0))
                    {
                        JL_UART0->BUF =LSCOM[i];
                        __asm__ volatile("csync");
                        while ((JL_UART0->CON0 & BIT(15)) == 0);
                        JL_UART0->CON0 |= BIT(13);
                    }
               }
             }
             else if((rbuf[2]==0xC3)&(rbuf[3]==0x6E))//回读固件版本号使用的
             {
               //printf("YRZ%d%d",SYS_GJBB_V1,SYS_GJBB_V2);
               LSCOM[0]='Y';
               LSCOM[1]='R';
               LSCOM[2]='Z';//表示主机
               LSCOM[3]=SYS_GJBB_V1;//固件版本号的整数位
               LSCOM[4]=SYS_GJBB_V2;//固件版本号的小时位
               //put_buf(LSCOM, 5);//发送返回串口值
               for(i=0;i<5;i++)
               {
                 //put_u8hex(LSCOM[i]);//测试一下是否是单个发送
                    if(JL_UART0->CON0 & BIT(0))
                    {
                        JL_UART0->BUF =LSCOM[i];
                        __asm__ volatile("csync");
                        while ((JL_UART0->CON0 & BIT(15)) == 0);
                        JL_UART0->CON0 |= BIT(13);
                    }
               }
            }
         }
      }
      else if(len==7)//设置ID值使用的
      {
         if((rbuf[0]=='Y')&(rbuf[1]=='R')&(rbuf[2]==0xC1))
         {
            LSX=0x16C+rbuf[3]+rbuf[4]+rbuf[5];
            LSX%=256;
            if(LSX==rbuf[6])//表示校验成功
            {
               syscfg_write(CFG_USER_DEFINE_24GSN, &rbuf[3], 4);
               LSX=syscfg_read(CFG_USER_DEFINE_24GSN, SYS_24G_SN_BYTE, 4);
               LSCOM[0]='Y';
               LSCOM[1]='R';
               if(LSX==0)//写入失败
               {
                 LSCOM[2]='E';
                 LSCOM[3]='R';
               }
               else//写入成功
               {
                 LSCOM[2]='O';
                 LSCOM[3]='K';
               }
               //put_buf(LSCOM, 4);//发送返回串口值
               for(i=0;i<4;i++)
               {
                 //put_u8hex(LSCOM[i]);//测试一下是否是单个发送
                    if (JL_UART0->CON0 & BIT(0))
                    {
                        JL_UART0->BUF =LSCOM[i];
                        __asm__ volatile("csync");
                        while ((JL_UART0->CON0 & BIT(15)) == 0);
                        JL_UART0->CON0 |= BIT(13);
                    }
               }
            }
         }
      }
       //log_info("uart_rx_dataXX %d:", len);
       //put_buf(rbuf, len);
    }

    if (uart_db_irq_handler_callback) {
        uart_db_irq_handler_callback(rbuf, len);
    }
}

void uart_db_regiest_recieve_callback(void *rx_cb)
{
    uart_db_irq_handler_callback = rx_cb;
}


u32 stack_magic[4] sec(.stack_magic);
u32 stack_magic0[4] sec(.stack_magic0);
void memory_init(void);

void setup_arch()
{
#if TCFG_CHARGE_ENABLE
    //防止LDOIN先上电,VBAT后上电导致的VDC12过压(越靠前调用越好)
    extern void power_enter_charge_mode(void);
    power_enter_charge_mode();
#endif

    //asm("trigger ");
    JL_UART0->CON0 |= BIT(2); //use lp waiting, must set Tx pending Enable

    memory_init();
    memset(stack_magic, 0x5a, sizeof(stack_magic));
    memset(stack_magic0, 0x5a, sizeof(stack_magic0));

    //P11 系统必须提前打开
    p11_init();

    wdt_init(WDT_4S);
    /* wdt_close(); */

    clk_voltage_init(TCFG_CLOCK_MODE, SYSVDD_VOL_SEL_126V);
    clk_early_init(TCFG_CLOCK_SYS_SRC, TCFG_CLOCK_OSC_HZ, TCFG_CLOCK_SYS_HZ);

    tick_timer_init();
    /*interrupt_init();*/

#if (defined CONFIG_DEBUG_ENABLE) || (defined CONFIG_DEBUG_LITE_ENABLE)
    debug_uart_init(NULL);

#if TCFG_UART0_RX_PORT != NO_CONFIG_PORT
    JL_UART0->CON0 &= ~BIT(2); //disable Tx pending Enable
    uart_dev_set_irq_handler_hook(uart_db_irq_handler_hook);

#if TCFG_LOWPOWER_LOWPOWER_SEL
    /*需要关闭POWERDOWN,否则接收会丢数据*/
#error "need define TCFG_LOWPOWER_LOWPOWER_SEL  0 !!!!!!"
#endif
#endif

#ifdef CONFIG_DEBUG_ENABLE
    log_early_init(1024);
#endif

#endif

    log_i("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    log_i("         setup_arch %s %s", __DATE__, __TIME__);
    log_i("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");

    clock_dump();

    efuse_dump();

    reset_source_dump();

    /* power_reset_source_dump(); */

    //Register debugger interrupt
    request_irq(0, 2, exception_irq_handler, 0);
    request_irq(1, 2, exception_irq_handler, 0);

    sys_timer_init();

    debug_init();

    /* sys_timer_add(NULL, timer, 1 * 1000); */


    __crc16_mutex_init();
}

/*-----------------------------------------------------------*/
